package scala.examples.tcpoly.calculi.lambda.full

import scala.util.parsing.combinator.syntactical.StdTokenParsers
import scala.util.parsing.combinator.lexical.StdLexical
import scala.util.parsing.combinator.Parsers
import scala.util.parsing.combinator.~

trait BindingParsers { self: Parsers with Binding with BindingParsers =>
  def bind(nameParser: => Parser[String]): Parser[Name] = nameParser ^^ (Name(_))
  def bound(nameParser: => Parser[String]): Parser[Name] = error("TODO") // look up in env
  def inScope[T](x: Name)(p: => Parser[T]): Parser[\\[T]] = error("TODO") // run p in extended env  
}

trait Parsers extends BindingParsers with StdTokenParsers { self: Syntax with Binding with Parsers =>
  type Tokens = StdLexical; val lexical = new StdLexical
  lexical.delimiters ++= List("\\",".")
  
  def term: Parser[Term] = 
    ( bound(ident)                                ^^ {case x => Var(x)} 
    | keyword("\\") ~ bind(ident) >> {x => keyword(".") ~ inScope(x)(term)} ^^ {case body => Abs(body)  }
    | chainl1(term, success(App(_: Term, _: Term)))
    )
}

object TestParser extends Parsers with Syntax with Binding with Application  {
 def parse(in: String) = phrase(term)(new lexical.Scanner(in))
 println(parse("\\x. \\y.y"))
}